﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Specialized;

namespace DataCodeDemo
{
    public class HControlManager
    {
        private HWindowControl _hwControl;

        private HImage _hImage;      
        
        public HImage HImage
        {
            get { return _hImage; }
            set
            {
                if(_hImage!=value)
                {
                    _hImage?.Dispose();
                    _hImage = value;
                    UpdateWindow(true);
                }               
            }
        }

        public ObservableCollection<HXLDInfo> HXLDInfos { get; set; } = new ObservableCollection<HXLDInfo>();

        public ObservableCollection<RegionInfo> RegionInfos { get; set; } = new ObservableCollection<RegionInfo>();

        public ObservableCollection<TextInfo> TextInfos { get; set; } = new ObservableCollection<TextInfo>();

        public HControlManager(HWindowControl hwControl)
        {
            _hwControl = hwControl;
            HXLDInfos.CollectionChanged += HXLDInfos_CollectionChanged;
            RegionInfos.CollectionChanged += RegionInfos_CollectionChanged;
            TextInfos.CollectionChanged += TextInfos_CollectionChanged;
        }

        private void HXLDInfos_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add) UpdateWindow();
            else UpdateWindow(false, true);
        }

        private void RegionInfos_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add) UpdateWindow();
            else UpdateWindow(false, true);
        }

        private void TextInfos_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add) UpdateWindow();
            else UpdateWindow(false, true);
        }
        
        private void UpdateWindow(bool isNewImage=false,bool isRemoveGraph=false)
        {
            if(isNewImage)
            {
                FitImage(HImage);
                HXLDInfos.CollectionChanged -= HXLDInfos_CollectionChanged;
                RegionInfos.CollectionChanged -= RegionInfos_CollectionChanged;
                TextInfos.CollectionChanged -= TextInfos_CollectionChanged;
                HXLDInfos.Clear();
                RegionInfos.Clear();
                TextInfos.Clear();
                HXLDInfos.CollectionChanged += HXLDInfos_CollectionChanged;
                RegionInfos.CollectionChanged += RegionInfos_CollectionChanged;
                TextInfos.CollectionChanged += TextInfos_CollectionChanged;
            }
            if (isNewImage || isRemoveGraph) 
            {
                HSystem.SetSystem("flush_graphic", "false");
                _hwControl.HalconWindow.ClearWindow();
                HSystem.SetSystem("flush_graphic", "true");
                HImage?.DispObj(_hwControl.HalconWindow);               
            }         
            foreach (var hxldInfo in HXLDInfos)
            {
                if (hxldInfo.HXLD != null)
                {
                    if (hxldInfo.Color != string.Empty) _hwControl.HalconWindow.SetColor(hxldInfo.Color);
                    if (hxldInfo.LineWidth > 0) _hwControl.HalconWindow.SetLineWidth(hxldInfo.LineWidth);
                    _hwControl.HalconWindow.DispObj(hxldInfo.HXLD);
                }
            }
            foreach (var regionInfo in RegionInfos)
            {
                if (regionInfo.HRegion != null)
                {
                    if (regionInfo.Color != string.Empty) _hwControl.HalconWindow.SetColor(regionInfo.Color);
                    if (regionInfo.DrawMode != string.Empty) _hwControl.HalconWindow.SetDraw(regionInfo.DrawMode);
                    _hwControl.HalconWindow.DispObj(regionInfo.HRegion);
                }
            }
            foreach (var textInfo in TextInfos)
            {
                if (textInfo.Text != string.Empty)
                {
                    if (textInfo.Color != string.Empty) _hwControl.HalconWindow.SetColor(textInfo.Color);
                    if (textInfo.Font != string.Empty) _hwControl.HalconWindow.SetFont(textInfo.Font);
                    if (textInfo.LineWidth > 0) _hwControl.HalconWindow.SetLineWidth(textInfo.LineWidth);
                    _hwControl.HalconWindow.SetTposition(textInfo.Location.X, textInfo.Location.Y);
                    _hwControl.HalconWindow.WriteString(textInfo.Text);
                }
            }
        }

        private void FitImage(HImage hImage)
        {
            double ratio_win, ratio_img;
            hImage.GetImageSize(out int width, out int height);
            ratio_win = _hwControl.Width / (double)_hwControl.Height;
            ratio_img = (double)width / height;
            int _beginRow, _begin_Col, _endRow, _endCol;
            if (ratio_win >= ratio_img)
            {
                _beginRow = 0;
                _endRow = height - 1;
                _begin_Col = (int)(-width * (ratio_win / ratio_img - 1) / 2d);
                _endCol = (int)(width + width * (ratio_win / ratio_img - 1) / 2d);
            }
            else
            {
                _begin_Col = 0;
                _endCol = width - 1;
                _beginRow = (int)(-height * (ratio_img / ratio_win - 1) / 2d);
                _endRow = (int)(height + height * (ratio_img / ratio_win - 1) / 2d);
            }
            _hwControl.HalconWindow.SetPart(_beginRow, _begin_Col, _endRow, _endCol);
        }
    }

    public class HXLDInfo
    {
        public HXLD HXLD { get; set; }
        public string Color { get; set; }
        public int LineWidth { get; set; }
    }

    public class RegionInfo
    {
        public HRegion HRegion { get; set; }
        public string Color { get; set; }
        public string DrawMode { get; set; }
    }

    public class TextInfo
    {
        public string Text { get; set; }
        public string Color { get; set; }
        public string Font { get; set; }
        public Point Location { get; set; } = new Point(0, 0);
        public int LineWidth { get; set; }
    }
}
